package com.kylin.absfactory.a;

/**
 * 针对于工厂方法的问题，当有多个产品等级时（食物，饮料，甜品。。。）工厂类就会有很多
 * 修改代码如下，使用抽象工厂设计模式
 */


//抽象产品
interface Food {
    void eat();
}

//具体产品
class Hamburger implements Food {

    @Override
    public void eat() {
        System.out.println("吃汉堡包");
    }
}

//具体产品
class RiceNoodle implements Food {

    @Override
    public void eat() {
        System.out.println("过桥米线");
    }
}

interface Factory {
    Drink getDrink();

    Food getFood();

}

class KFCFactory implements Factory {

    @Override
    public Drink getDrink() {
        return new Cola();
    }

    @Override
    public Food getFood() {
        return new Hamburger();
    }
}

class SanQinFactory implements Factory {

    @Override
    public Drink getDrink() {
        return new IcePeak();
    }

    @Override
    public Food getFood() {
        return new RiceNoodle();
    }
}

//抽象产品
interface Drink {
    void drink();
}

//具体产品
class Cola implements Drink {

    @Override
    public void drink() {
        System.out.println("可口可乐");
    }
}

//具体产品
class IcePeak implements Drink {

    @Override
    public void drink() {
        System.out.println("冰峰饮料");
    }
}

//-------------------------------------
class Lp implements Food {

    @Override
    public void eat() {
        System.out.println("凉皮");
    }
}

class FenDa implements Drink {

    @Override
    public void drink() {
        System.out.println("芬达饮料");
    }
}

class BaoJiFactory implements Factory {

    @Override
    public Drink getDrink() {
        return new FenDa();
    }

    @Override
    public Food getFood() {
        return new Lp();
    }
}

class Business {
    public static void taste(Factory foodFactory) {
        Food food = foodFactory.getFood();
        Drink drink = foodFactory.getDrink();
        System.out.println("评委1，品尝");
        food.eat();
        drink.drink();

        Food food2 = foodFactory.getFood();
        Drink drink2 = foodFactory.getDrink();
        System.out.println("评委2，品尝");
        food2.eat();
        drink2.drink();

        Food food3 = foodFactory.getFood();
        Drink drink3 = foodFactory.getDrink();
        System.out.println("评委3，品尝");
        food3.eat();
        drink3.drink();
    }

}

public class AppTest {
    public static void main(String[] args) {
        Business.taste(new KFCFactory());
        Business.taste(new BaoJiFactory());

        Factory factory = new BaoJiFactory();
        Drink drink = factory.getDrink();
        drink.drink();
    }
}
/**
 * 抽象工厂
 * 优点：
 * 1.仍有简单工厂和工厂方法的优点
 * 2.更重要的是，抽象工厂把工厂类的数量减少了！无论有多少个产品等级，工厂就一套。
 * <p>
 * 杠点：
 * 1.为什么三秦工厂中，就必须是米线搭配冰峰呢？为什么就不能是米线搭配可乐？
 * <p>
 * 解释：
 * 抽象工厂中，可以生产多个产品，这多个产品之间，必须有内在联系。
 * 同一个工厂中的产品都属于同一个产品簇！不能把不同产品簇中的产品混合到一个抽象工厂的实现类中。
 * <p>
 * 缺点：
 * 1.当产品等级发生变化时（增加产品等级，删除产品等级），都要引起所有以前工厂代码的修改，这就违反了“开闭原则”
 * <p>
 * <p>
 * 结论：
 * 当产品等级比较固定时，可以考虑使用抽象工厂
 * 当产品等级经常变化，则不建议使用抽象工厂
 */
